package com.stone.serverless.auth.interceptor;

import cn.dev33.satoken.exception.BackResultException;
import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.exception.StopMatchException;
import cn.dev33.satoken.router.SaRouteFunction;
import cn.dev33.satoken.router.SaRouter;
import cn.dev33.satoken.servlet.model.SaRequestForServlet;
import cn.dev33.satoken.servlet.model.SaResponseForServlet;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.ReflectUtil;
import com.stone.serverless.auth.domain.FilterContext;
import com.stone.serverless.auth.handler.RequestResponseInvokeHandler;
import com.stone.serverless.sdk.ProxyClassConfig;
import lombok.SneakyThrows;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @Description: TODO
 * @Author: MECHREVO
 * @Date: 2022/1/27 9:18
 * @Version: 1.0.0
 */
public class SaRouteInterceptor implements StoneHandlerInterceptor {

    /**
     * 每次进入拦截器的[执行函数]，默认为登录校验
     */
    public SaRouteFunction function = (req, res, handler) -> StpUtil.checkLogin();

    /**
     * 创建一个路由拦截器
     */
    public SaRouteInterceptor() {
    }

    /**
     * 创建, 并指定[执行函数]
     *
     * @param function [执行函数]
     */
    public SaRouteInterceptor(SaRouteFunction function) {
        this.function = function;
    }

    /**
     * 静态方法快速构建一个
     *
     * @param function 自定义模式下的执行函数
     * @return sa路由拦截器
     */
    public static SaRouteInterceptor newInstance(SaRouteFunction function) {
        return new SaRouteInterceptor(function);
    }


    // ----------------- 验证方法 -----------------

    @SneakyThrows
    @Override
    public Boolean preHandle(FilterContext filterContext) {
        Object servletRequest = filterContext.getRequest().getServletRequest();

        HttpServletRequest proxyServletRequest = (HttpServletRequest) ProxyClassConfig.proxy(HttpServletRequest.class, this.getClass().getClassLoader(),
                new RequestResponseInvokeHandler(servletRequest));

        Object servletResponse = filterContext.getResponse().getServletResponse();
        HttpServletResponse proxyServletResponse = (HttpServletResponse) ProxyClassConfig.proxy(HttpServletResponse.class, this.getClass().getClassLoader(),
                new RequestResponseInvokeHandler(servletResponse));
        //直接把他代理掉

        ServletRequestAttributes servletRequestAttributes =
                ReflectUtil.newInstance(ServletRequestAttributes.class, proxyServletRequest, proxyServletResponse);
        RequestContextHolder.setRequestAttributes(servletRequestAttributes);
        SaRequestForServlet saRequestForServlet = ReflectUtil.newInstance(SaRequestForServlet.class,
                proxyServletRequest);
        //
        SaResponseForServlet saResponseForServlet = ReflectUtil.newInstance(SaResponseForServlet.class,
                proxyServletResponse);

        try {

            SaRouter.match("/**", "/**/doLogin", r -> StpUtil.checkLogin());

          //  function.run(saRequestForServlet, saResponseForServlet, filterContext.getHandler());
        } catch (StopMatchException e) {
            // 停止匹配，进入Controller
        } catch (NotLoginException e) {
            if (proxyServletResponse.getContentType() == null) {
                proxyServletResponse.setContentType("text/plain; charset=utf-8");
            }
            proxyServletResponse.getWriter().print("没有登录啊");
            return false;
            // 停止匹配，进入Controller
        }  catch (BackResultException e) {
            // 停止匹配，向前端输出结果
            if (proxyServletResponse.getContentType() == null) {
                proxyServletResponse.setContentType("text/plain; charset=utf-8");
            }
            proxyServletResponse.getWriter().print(e.getMessage());
            return false;
        } finally {
           // RequestContextHolder.resetRequestAttributes();
        }
        return true;
    }

    @Override
    public void finishRequest() {
        RequestContextHolder.resetRequestAttributes();
    }
}
